package cn.signalpha.common.aspect;

import cn.hutool.core.util.StrUtil;
import cn.signalpha.common.annotation.FormRepeatCommitAnnotation;
import cn.signalpha.core.log.exception.ServiceException;
import cn.signalpha.core.redis.cache.RedisCache;
import cn.signalpha.core.tool.utils.StringPool;
import cn.signalpha.core.tool.utils.WebUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 表单重复提交AOP
 *
 * @author signalpha
 */
@Slf4j
@Aspect
@Component
@AllArgsConstructor
public class FormRepeatCommitAspect implements Ordered {

	private final RedisCache redisUtil;

	@Around("@annotation(cn.signalpha.common.annotation.FormRepeatCommitAnnotation)")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		HttpServletRequest request  = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
		MethodSignature signature = (MethodSignature) point.getSignature();
		Method method = signature.getMethod();
		FormRepeatCommitAnnotation avoidRepeatableCommit =  method.getAnnotation(FormRepeatCommitAnnotation.class);
		String key = StrUtil.format("{}:{}", request.getRequestURI(), WebUtil.getIP(request));
		if (redisUtil.exists(key)){
			throw new ServiceException(avoidRepeatableCommit.message());
		}
		redisUtil.setEx(key, StringPool.ZERO, avoidRepeatableCommit.intervalSecond());
		return point.proceed();
	}

	@Override
	public int getOrder() {
		return Ordered.HIGHEST_PRECEDENCE;
	}
}
